<?php
declare (strict_types=1);

namespace quick\admin\library\service;


use quick\admin\library\service\token\Driver;
use quick\admin\Service;
use think\exception\InvalidArgumentException;
use think\facade\Config;
use think\helper\Arr;
use think\helper\Str;

/**
 *
 * Class EmailService
 * @package quick\librarys
 */
class TokenService extends Service
{

    /**
     * @var array
     */
    public array $instance = [];

    /**
     * @var object token驱动类句柄
     */
    public object $handler;

    /**
     * 驱动类命名空间
     */
    protected string $namespace = 'quick\\admin\\library\\service\\token\\driver';


    /**
     * @param string|null $name
     * @return Driver
     */
    public function getDriver(string $name = null):Driver
    {
        if (!is_null($this->handler)) {
            return $this->handler;
        }
        $name = $name ?: $this->getConfig('default');

        if (is_null($name)) {
            throw new InvalidArgumentException(sprintf(
                'Unable to resolve NULL driver for [%s].',
                static::class
            ));
        }

        return $this->createDriver($name);
    }

    /**
     * 创建驱动句柄
     * @param string $name
     * @return mixed
     */
    protected function createDriver(string $name)
    {
        $type = (string)$this->resolveType($name);

        $config = $this->getDriveConfig($name);

        $class = $this->resolveClass($type);

        if (isset($this->instance[$type])) {
            return $this->instance[$type];
        }

        return new $class(...[$config]);
    }

    /**
     * 获取驱动配置
     * @param string      $store
     * @param string|null $name
     * @param null        $default
     * @return array|string
     */
    protected function getDriveConfig(string $store, string $name = null, $default = null)
    {
        if ($config = $this->getConfig("drives.{$store}")) {
            return Arr::get($config, $name, $default);
        }

        throw new InvalidArgumentException("Drive [$store] not found.");
    }

    /**
     * 获取驱动类
     * @param string $type
     * @return string
     */
    protected function resolveClass(string $type): string
    {
        if ($this->namespace || false !== strpos($type, '\\')) {
            $class = false !== strpos($type, '\\') ? $type : $this->namespace . Str::studly($type);

            if (class_exists($class)) {
                return $class;
            }
        }
        throw new InvalidArgumentException("Driver [$type] not supported.");
    }


    /**
     * 获取驱动配置
     * @param string|null $name
     * @param null        $default
     * @return mixed
     */
    protected function getConfig(string $name = null, $default = null)
    {
        if (!is_null($name)) {
            return Config::get('quick.token.' . $name, $default);
        }

        return Config::get('quick.token');
    }


    /**
     * @param string $token
     * @param bool $expirationException
     * @return array
     */
    public function getToken(string $token, bool $expirationException = true):array
    {
        return $this->getDriver()->getToken($token,$expirationException);
    }


    /**
     * @param string $token
     * @param int $user_id
     * @param int $expire
     * @return bool
     */
    public function setToken(string $token, int $user_id, int $expire = 0):bool
    {
        return $this->getDriver()->setToken($token,$user_id,$expire);
    }


    /**
     * @param string $token
     * @param int $user_id
     * @param bool $expirationException
     * @return bool
     */
    public function check(string $token, int $user_id, bool $expirationException = true):bool
    {
        return $this->getDriver()->check($token,$user_id,$expirationException);
    }


    /**
     * 删除一个token
     * @param string $token
     */
    public function delete(string $token)
    {

    }


    /**
     * 清理一个用户的所有token
     * @param int $user_id
     */
    public function clear(int $user_id)
    {

    }
}
